package com.ruben.controller;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.fastjson.JSON;
import com.aliyuncs.utils.StringUtils;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruben.config.RabbitmqConfig;
import com.ruben.constant.UserConstant;
import com.ruben.dao.MpOrderMapper;
import com.ruben.pojo.User;
import com.ruben.pojo.UserInfo;
import com.ruben.pojo.dto.EmailDataTransferObject;
import com.ruben.pojo.dto.PageDTO;
import com.ruben.pojo.po.OrderPO;
import com.ruben.pojo.po.UserPO;
import com.ruben.pojo.to.SmsTO;
import com.ruben.pojo.to.UserTO;
import com.ruben.pojo.vo.UserVO;
import com.ruben.service.UserService;
import com.ruben.task.SendEmailTask;
import com.ruben.utils.AjaxJson;
import lombok.SneakyThrows;
import org.apache.commons.lang.time.DateUtils;
import org.aspectj.weaver.ast.Or;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessagePropertiesBuilder;
import org.springframework.context.annotation.DependsOn;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.beans.PropertyEditorSupport;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @ClassName: UserController
 * @Description:
 * @Date: 2020/8/6 19:56
 * *
 * @author: achao<achao1441470436 @ gmail.com>
 * @version: 1.0
 * @since: JDK 1.8
 */
@RestController
@RequestMapping("user")
@DependsOn("SpringContextHolder")
public class UserController {

    @Resource
    private HttpServletRequest httpServletRequest;
    //    private static final UserService userService = SpringContextHolder.getBean(UserService.class);
    @Resource
    private UserService userService;
    @Resource
    private AmqpTemplate amqpTemplate;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private MpOrderMapper mpOrderMapper;


    /**
     * 登录失败时调用该接口
     *
     * @return 返回json格式的map
     */
    @GetMapping("shout")
    public AjaxJson shout() {
        return AjaxJson.success("哼哼啊啊啊啊啊啊啊啊啊啊");
    }

    /**
     * 登录成功时调用该接口，传入一句话
     *
     * @param word 参数 例子：?word=登录成功！
     * @return 返回json格式的map
     */
    @GetMapping("say")
    @SentinelResource
    public AjaxJson say(@RequestParam String word) {
        return AjaxJson.success().put("data", word);
    }

    /**
     * 登录
     *
     * @param user 参数为Json格式的User对象{"username":"","password":""}
     * @return 返回json格式的map
     */
    @PostMapping("login")
    public AjaxJson login(@Valid @RequestBody User user) {
        UserPO userPO = userService.validateUser(user);
        if (userPO == null) {
            return AjaxJson.error("用户名或密码错误");
        }
        //生成token(在每个请求头里加上，用于判断用户登录状态)
        String token = userService.createToken(userPO, UserConstant.TOKEN_EXPIRE_TIME);
        //生成refreshToken（用于在用户token过期情况下刷新token）
        String refreshToken = userService.createToken(userPO, UserConstant.REFRESH_TOKEN_EXPIRE_TIME);
        return AjaxJson.success("登陆成功！")
                .put("token", token)
                .put("refreshToken", refreshToken);
    }

    /**
     * 刷新token
     *
     * @param refreshToken
     * @return
     */
    @GetMapping("refreshToken")
    public AjaxJson refreshToken(String refreshToken) {
        return userService.refreshToken(refreshToken);
    }

    @GetMapping("logout")
    public AjaxJson logout() {
        String token = userService.getToken(httpServletRequest);
        if (StringUtils.isNotEmpty(token)) {
            userService.logout(token);
        }
        return AjaxJson.success("已注销");
    }


    /**
     * 批量更改用户信息
     *
     * @param userInfoList
     * @return
     */
    @PostMapping("batchUpdateUserInfo")
    public AjaxJson batchUpdateUserInfo(@RequestBody @Valid List<UserInfo> userInfoList) {
        return AjaxJson.success().put("data", userInfoList);
    }

    /**
     * 获取用户列表
     *
     * @return
     */
    @PostMapping("userList")
    public AjaxJson userList(@RequestBody PageDTO pageDTO) {
        IPage<UserPO> page = userService.findList(pageDTO);
        // 过滤密码
        page.setRecords(page.getRecords().stream().peek(userPO -> userPO.setPassword(null)).collect(Collectors.toList()));
        return AjaxJson.success("查询成功！").put("data", page);
    }

    @GetMapping("say/{word}")
    public AjaxJson speak(@PathVariable String word) {
        return AjaxJson.success().put("data", word);
    }

    @PostMapping("register")
    public AjaxJson register(@Validated({User.AddCheck.class}) @RequestBody User user) {
        UserPO localUser = userService.findUserByUsername(user.getUsername());
        if (localUser != null) {
            return AjaxJson.error("用户名已被注册");
        }
        String errorMsg = userService.register(user);
        if (StringUtils.isNotEmpty(errorMsg)) {
            return AjaxJson.error(errorMsg);
        }
        return AjaxJson.success();
    }

    @PostMapping("sendEmail")
    public AjaxJson sendEmail(@RequestBody @Validated EmailDataTransferObject emailDataTransferObject) {
        SendEmailTask.sendEmail(emailDataTransferObject);
        return AjaxJson.success("发送成功！");
    }

    @PostMapping("findUserList")
    public AjaxJson findUserList(@RequestBody PageDTO pageDTO) {
        // DTO转换为TO，用于向service层传输
        UserTO param = new UserTO();
        param.setPageNum(pageDTO.getPageNum());
        param.setPageSize(pageDTO.getPageSize());
        param.setUsername(pageDTO.getKeywords());
        UserTO result = userService.findUserList(param);
        // TO转换成VO，用于向页面展示
        List<UserVO> userVOList = result.getDataList().stream().map(data -> UserVO.builder().id(data.getUser().getId()).username(data.getUser().getUsername()).phoneNumber(data.getUserInfo().getPhoneNumber()).build()).collect(Collectors.toList());
        return AjaxJson.success().put("total", result.getTotal()).put("pageNum", result.getPageNum()).put("pageSize", result.getPageSize()).put("data", userVOList);
    }

    @GetMapping("sendSms/{number}")
    public AjaxJson sendSms(@PathVariable String number) {
        // 获取code
        SecureRandom random = new SecureRandom();
        String code = random.ints(100000, 999999).boxed().findAny().map(String::valueOf).orElseThrow(RuntimeException::new);
        // 往数据库存number
        stringRedisTemplate.opsForValue().set(number, code, 5, TimeUnit.MINUTES);
        // 发消息到RabbitMQ
        amqpTemplate.send(RabbitmqConfig.EXCHANGE_RUBEN, RabbitmqConfig.ROUTING_KEY_RUBEN, MessageBuilder.withBody(JSON.toJSONString(SmsTO.builder().number(number).code(code).build()).getBytes(StandardCharsets.UTF_8)).andProperties(MessagePropertiesBuilder.newInstance().setExpiration("5000").build()).build());
        return AjaxJson.success("发送成功！");
    }

    @GetMapping("order")
    public AjaxJson order() {
        return userService.order();
    }

    /**
     * 修改发货时间
     *
     * @param order 订单实体
     * @author <achao1441470436@gmail.com>
     * @date 2021/4/4 0004 23:21
     */
    @PostMapping("changeOrder")
    public AjaxJson changeOrder(@RequestBody OrderPO order) {
        mpOrderMapper.updateById(order);
        return AjaxJson.success();
    }

    @PostMapping("testDate")
    public AjaxJson testDate(OrderPO orderPO) {
        return AjaxJson.success().put("data", orderPO);
    }


}
